package cn.chowx.myjfinal.shiro;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;

import cn.chowx.myjfinal.system.model.SysAction;
import cn.chowx.myjfinal.system.model.SysRole;
import cn.chowx.myjfinal.system.model.SysUser;
import cn.dreampie.shiro.core.SubjectKit;

/**
 * JDBC shiroRealm
 * @author zcqshine
 *
 */
public class MyShiroRealm extends AuthorizingRealm {

	/**
	 * 授权查询回调方法, 进行鉴权但缓存中无用户的授权信息时调用
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SysUser user_auth = (SysUser)principals.fromRealm(getName()).iterator().next();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		Set<String> roleSet = new LinkedHashSet<>(); //角色集合
		Set<String> actionSet = new LinkedHashSet<>();//权限集合
		List<SysRole> roles = null;
		SysUser user = SysUser.DAO.findById(user_auth.getInt("id"));
		if(user != null){
			roles = user.getRolesByUserId();
		}else{
			SubjectKit.getSubject().logout();
		}
		
		loadRole(roleSet,actionSet,roles);
		info.setRoles(roleSet);					//设置角色
		info.setStringPermissions(actionSet); 	//设置权限
		return info;
	}

	/**
	 * 认证回调, 登录时调用
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
		SysUser user = SysUser.DAO.getSysUserByAccount(token.getUsername());
		if(user != null){
			Session session = SecurityUtils.getSubject().getSession();
			session.setAttribute("account", user.getStr("account"));
			return new SimpleAuthenticationInfo(user,user.getStr("password"),getName());
		}
		return null;
	}
	
	/**
	 * 
	 * @param roleSet
	 * @param actionSet
	 * @param roles
	 */
	private void loadRole(Set<String> roleSet,Set<String> actionSet, List<SysRole> roles){
		List<SysAction> actions;
		if(roles != null && !roles.isEmpty()){
			for(SysRole role : roles){
				if(role.getInt("status") == 1){
					roleSet.add(role.getStr("value"));
					actions = role.getActionsByRoleId();
					loadAuth(actionSet, actions);
				}
			}
		}
	}
	
	/**
	 * 
	 * @param actionSet
	 * @param actions
	 */
	private void loadAuth(Set<String> actionSet, List<SysAction> actions){
		if(actions != null && !actions.isEmpty()){
			//遍历权限
			for(SysAction action : actions){
				if(action.getInt("status") == 1){
					actionSet.add(action.getStr("value"));
				}
			}
		}
	}
	
	/**
	 * 更新用户授权信息缓存
	 * @param principal
	 */
	public void clearCachedAuthorizationInfo(Object principal){
		SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
		clearCachedAuthorizationInfo(principals);
	}
	
	/**
	 * 清除所有用户授权信息缓存
	 */
	public void clearAllCachedAuthorizationInfo(){
		Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
		if(cache != null){
			for(Object key : cache.keys()){
				cache.remove(key);
			}
		}
	}
}
